﻿/**
 * @file DyByteBuff.cc
 * @brief dynamic byte buffer
 * $Id: DyByteBuff.cc 13 2011-01-01 11:48:27Z tonyjobmails $
 * $Date: 2011-01-01 11:48:27 +0000 (Sat, 01 Jan 2011) $
 * $Author: tonyjobmails $
 * $Revision: 13 $
 */

#include <strings.h>
#include <string.h>
#include "DyByteBuff.h"
 
 /**
  * @brief  write the data into the buffer
  * @param _data：addr of the data
  * @param _size：size of the data
  */
void DyByteBuff::write(const unsigned char *_data, const unsigned int _size)
{
	if(_data && _size)
	{
		BUFF_ASSERT((((unsigned int)(-1) - this->_M_size) > _size));
		
		this->prewrite(_size);
		bcopy(_data, this->wr_ptr(), _size);
		wr_shiftout(_size);
	}
}

 /**
  * @brief check the space or allocate the buffer
  */
void DyByteBuff::prewrite(const unsigned int _size)
{
	if(this->wr_size() < _size)
	{
		unsigned int alloc_size = _UNIT_BUFF_SIZE * ((_size + _UNIT_BUFF_SIZE) / _UNIT_BUFF_SIZE);
		
		BUFF_ASSERT(alloc_size);
		
		this->_M_size += alloc_size;
		this->_M_buffer.resize(this->_M_size);
	}
}

 /**
  * @brief get the write addr of the buffer
  * @return the write addr
  */
unsigned char* DyByteBuff::wr_ptr()
{
	return &(this->_M_buffer[this->_M_wr_ptr]);
}
		
 /**
  * @brief get the read addr of the buffer
  * @return the read addr
  */
unsigned char* DyByteBuff::rd_ptr()
{
	return &(this->_M_buffer[this->_M_rd_ptr]);
}

 /**
  * @brief get the size of data
  * @return the size of data
  */
unsigned int DyByteBuff::rd_size()
{
	BUFF_ASSERT(this->_M_wr_ptr >= this->_M_rd_ptr);
	return this->_M_wr_ptr - this->_M_rd_ptr;
}

 /**
  * @brief get the residua space of the buffer
  * @return the residua space
  */
unsigned int DyByteBuff::wr_size()
{
	BUFF_ASSERT(this->_M_size >= this->_M_wr_ptr);
	return this->_M_size - this->_M_wr_ptr;
}

 /**
  * @brief arrange the buffer
  * @param _rd_size：the size of reading
  * @param _wr_size：the size of writing
  */
void DyByteBuff::shiftout(const unsigned int _rd_size, const unsigned int _wr_size)
{
	if(_rd_size)
		this->_M_rd_ptr += _rd_size;
	if(_wr_size)
		this->_M_wr_ptr += _wr_size;
		
	BUFF_ASSERT(this->_M_wr_ptr >= this->_M_rd_ptr);
	
	if(this->_M_rd_ptr > 0)
	{
		unsigned size = this->_M_wr_ptr - this->_M_rd_ptr;
		memmove(&(this->_M_buffer[0]), &(this->_M_buffer[this->_M_rd_ptr]), size);
		this->_M_rd_ptr = 0;
		this->_M_wr_ptr = size;
	}
}

 /**
  * @brief arrange the buffer after reading
  * @param _size：the size of reading
  */
void DyByteBuff::rd_shiftout(const unsigned int _size)
{
	this->shiftout(_size, 0);
}

 /**
  * @brief arrange the buffer after writing
  * @param _size：the size of writing
  */
void DyByteBuff::wr_shiftout(const unsigned int _size)
{
	this->shiftout(0, _size);
}

